package com.hmall.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hmall.common.client.ItemClient;
import com.hmall.common.client.UserClient;
import com.hmall.common.pojo.Address;
import com.hmall.common.pojo.Item;
import com.hmall.order.constants.MqConstants;
import com.hmall.order.context.BaseContext;
import com.hmall.order.mapper.OrderDetailMapper;
import com.hmall.order.mapper.OrderLogisticsMapper;
import com.hmall.order.mapper.OrderMapper;
import com.hmall.order.pojo.*;
import com.hmall.order.service.IOrderService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;

@Service
@RequiredArgsConstructor
public class OrderService extends ServiceImpl<OrderMapper, Order> implements IOrderService {

    private final ItemClient itemClient;

    private final OrderMapper orderMapper;

    private final UserClient userClient;

    private final OrderDetailMapper orderDetailMapper;

    private final OrderLogisticsMapper orderLogisticsMapper;

    private final RestHighLevelClient restHighLevelClient;

    private final RabbitTemplate rabbitTemplate;

    @Override
    @GlobalTransactional
    public OId createOrder(OrderDTO orderDTO) {
        //- 1）根据雪花算法生成订单id
        //  -mybaitplus自带
        //- 2）商品微服务提供FeignClient，实现根据id查询商品的接口
        //  -
        //- 3）根据itemId查询商品信息
        Item item = itemClient.rowInfo(orderDTO.getItemId());
        Integer stock = item.getStock();
        Integer sold = item.getSold();
        //判断库存是否足够
        if (stock < orderDTO.getNum()){
            throw new RuntimeException();
        }
        //- 4）基于商品价格、购买数量计算商品总价：totalFee
        //  -
        //- 5）封装Order对象，初始status为未支付，获取订单号
        //- 6）将Order写入数据库tb_order表中
        Long orderId = createOrder(orderDTO, item);
        //- 7）将商品信息、orderId信息封装为OrderDetail对象，写入tb_order_detail表
        createOrderDetail(orderDTO, item, orderId);
        //- 8）将user-service的根据id查询地址接口封装为FeignClient
        //  -
        //- 9）根据addressId查询user-service服务，获取地址信息
        Address address = userClient.findAddressById(orderDTO.getAddressId().longValue());
        //- 10）将地址封装为OrderLogistics对象，写入tb_order_logistics表
        createOrderLogistics(orderId,address);
        //- 11）在item-service提供减库存接口，并编写FeignClient
        //  -
        //- 12）调用item-service的减库存接口  减库存，加销量
        int stockUpdate = stock - orderDTO.getNum();
        int soldUpdate = sold + orderDTO.getNum();
        Item itemUpdate = new Item();
        itemUpdate.setId(item.getId());
        itemUpdate.setStock(stockUpdate);
        itemUpdate.setSold(soldUpdate);
        itemClient.update(itemUpdate);

        //更新es
        UpdateRequest request = new UpdateRequest("item", String.valueOf(item.getId()));
        request.doc(
                "stock",stockUpdate,
                "sold",soldUpdate
        );
        try {
            restHighLevelClient.update(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        rabbitTemplate.convertAndSend(MqConstants.ITEM_ORDER_EXCHANGE,MqConstants.ITEM_ORDER_KEY,orderId.toString());
        OId oId = new OId();
        oId.setId(orderId);
        return oId;
    }

    @Override
    public OrderDetail selectOrderDetailById(Long id) {
        LambdaQueryWrapper<OrderDetail> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(OrderDetail::getOrderId, id);
        return orderDetailMapper.selectOne(queryWrapper);
    }

    @Override
    public void deleteById(Long id) {
        orderLogisticsMapper.deleteById(id);
    }

    /**
     * 创建订单物流
     *
     * @param orderId 订单id
     * @param address 住址
     */
    private void createOrderLogistics(Long orderId, Address address) {
        OrderLogistics orderLogistics = new OrderLogistics();
        orderLogistics.setOrderId(orderId);
        orderLogistics.setLogisticsCompany("黑马物流");
        orderLogistics.setContact(address.getContact());
        orderLogistics.setMobile(address.getMobile());
        orderLogistics.setProvince(address.getProvince());
        orderLogistics.setCity(address.getCity());
        orderLogistics.setTown(address.getTown());
        orderLogistics.setStreet(address.getStreet());
        orderLogistics.setCreateTime(new Date());
        orderLogistics.setUpdateTime(new Date());
        orderLogisticsMapper.insert(orderLogistics);
    }

    /**
     * 创建订单详细信息
     *
     * @param orderDTO 订单dto
     * @param item     项目
     * @param orderId  订单id
     */
    private void createOrderDetail(OrderDTO orderDTO, Item item, Long orderId) {
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setOrderId(orderId);
        orderDetail.setItemId(item.getId());
        orderDetail.setNum(orderDTO.getNum());
        orderDetail.setName(item.getName());
        orderDetail.setPrice(item.getPrice());
        orderDetail.setSpec(item.getSpec());
        orderDetail.setImage(item.getImage());
        orderDetail.setCreateTime(new Date());
        orderDetail.setUpdateTime(new Date());
        orderDetailMapper.insert(orderDetail);
    }

    /**
     * 创建订单
     *
     * @param orderDTO 订单dto
     * @param item     项目
     * @return {@link Long}
     */
    private Long createOrder(OrderDTO orderDTO, Item item) {
        Order order = new Order();
        order.setTotalFee(item.getPrice() * orderDTO.getNum());
        order.setPaymentType(orderDTO.getPaymentType());
        order.setUserId(BaseContext.getUserId());
        order.setStatus(1);
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        //封装order对象,存入tb_order中
        orderMapper.insert(order);
        return order.getId();
    }
}
